use std::{pin::pin, time::Duration};



fn main() {
    // test1();
    test2();
}

// 此函数主要学习pin的用法，pin 主要用来固定内存位置
fn test1() {
    trpl::run(async {
        let (tx, mut rc) = trpl::channel();
        let tx2 = tx.clone();

        let tx1_fu = pin!(async move {
            let vals = vec![
                "1".to_string(),
                "2".to_string(),
                "3".to_string(),
                "4".to_string(),
            ];

            for va in vals {
                tx.send(va).unwrap();
                trpl::sleep(Duration::from_millis(500)).await;
            }
        });

        let tx2_fu = pin!(async move {
            let vals = vec![
                "5".to_string(),
                "6".to_string(),
                "7".to_string(),
                "8".to_string(),
            ];

            for va in vals {
                tx2.send(va).unwrap();
                trpl::sleep(Duration::from_millis(500)).await;
            }
        });

        let rc_fu = pin!(async move {
            while let Some(value) = rc.recv().await {
                println!("recv: {}", value);
            }
        });

        // 知道 future 数量的情况
        // trpl::join!(tx1_fu, tx2_fu, rc_fu);

        // tx1_fu, tx2_fu, rc_fu 在不包裹 pin! 的情况下，虽然推断出的方法签名一样，但不是同一个类型，所以不能放在同一泛型集合中，否则报错
        // let fus = vec![tx1_fu, tx2_fu, rc_fu];

        // 除了用 pin! 包裹，还得显示指明 Vec 的类型 <&mut dyn Future<Output = ()>>>。 pin中的 Future 还是在栈上
        let fus: Vec<std::pin::Pin<&mut dyn Future<Output = ()>>> = vec![tx1_fu, tx2_fu, rc_fu];
        // 不知道 future 数量的情况
        trpl::join_all(fus).await;

        // 如果推断出的方法签名不一样，pin! 包裹 都没用，老老实实的用 join! 方法
    });
}

fn test2() {
    trpl::run(async {

        let slow = async move {
            let vals = vec![
                "1".to_string(),
                "2".to_string(),
                "3".to_string(),
                "4".to_string(),
            ];

            for va in vals {
                println!(" {}", va);
                // trpl::sleep(Duration::from_millis(100)).await; // 睡眠阻塞，让出执行权
                trpl::yield_now().await; // 不睡眠，直接让出执行权，阻塞住
            }
        };

        let fast = async move {
            let vals = vec![
                "5".to_string(),
                "6".to_string(),
                "7".to_string(),
                "8".to_string(),
            ];

            for va in vals {
                println!(" {}", va);
                // trpl::sleep(Duration::from_millis(50)).await;// 睡眠阻塞，让出执行权
                trpl::yield_now().await; // 不睡眠，直接让出执行权，阻塞住
            }
        };
        // race 根据传入的 future 先后顺序来执行，每次遇到 异步阻塞才让出执行权， 
        trpl::race(slow, fast).await;
    });
}
